try:
   import gtk
   import gtk.glade
except: sys.exit(1)

import sys,os
import runtime
import gobject
import game
from pygame.locals import *
from GUI.constants import *
import GUI

def find_item_name(dic,item):
   a = [name for name in dic.keys() if dic[name] == item]
   if not len(a) == 1:
       return None
   else:
       return a[0]

def hide_window(widget=None,param2=None):
   """Standard Method to prevent a window being destroyed"""
   widget.hide()
   return True


class gtk_helper(object):

   def get_widget(self,name):
       return self.wTree.get_widget(name)

   def show_popup(self,name,event):
       """pops up a menu - e.g. on right click"""
       self.get_widget(name).popup(None, None, None
                       , event.button, event.time)


class main_window_events(gtk_helper):
   """not runnable by itself
      - inherit from it for the sake of code clarity
   """

   def check_quit(self,widget=None,other=None):
        msg = GUI.msgbox.gbConfirmMsgbox("Are you sure you want to quit?", modal=True)
        check = msg.run()
        msg.destroy()
        if check == gtk.RESPONSE_OK:
            gtk.main_quit()
        else: 
            return True

   def connect_events(self):
       """Connect the event handlers"""

       # Define event handlers for Gtk objects
       dic = { "on_wnd_main_destroy" : self.check_quit ,
               "on_wnd_sprite_delete_event" : hide_window,
               "on_new1_activate" : self.new_game,
               "on_quit1_activate" : self.check_quit,
               "on_open1_activate" : self.open_file,
               "on_save1_activate" : self.save_file,
               "on_save_as1_activate" : self.save_file_as,
               "on_about1_activate" : self.show_about,
               "on_refresh1_activate":self.treeviewhelp.update_item_list,
               "on_add_object1_activate":self.new_game_object,
               "on_add_child1_activate":self.add_child_workstate,
               "on_add_workstate1_activate":self.new_workstate,
               "on_play1_activate":self.run_game,
               "on_btn_run_clicked":self.run_game,
               "on_treeview1_row_activated":self.open_properties,
               "on_treeview_click":self.treeview_click,
               "on_btn_new_item_clicked":self.add_item_choice,
               "on_wnd_new_item_destroy_event":hide_window,
               "on_wnd_new_item_destroy_event":hide_window,
               "wnd_delete_event":hide_window,
               "on_cbxworkstateevents_changed":self.change_event_selected,
               "on_close1_activate":self.closegame,
               "btn_save_event":self.save_event,
               "on_btn_undo_event_changes":self.change_event_selected,
               "on_btn_workstate_ok":self.workstate_ok,
               "on_btn_gamescreen_colourpicker_clicked":self.choose_background_colour_gamescreen,
               "on_btn_gamescreen_ok_clicked":self.gamescreen_ok,
               "on_btn_obj_ok_clicked":self.object_ok,
               "on_btn_sprite_ok_clicked":self.sprite_ok,
               "on_gameproperties1_activate":self.show_game_properties,
               "on_mnu_import_sprite_activate":self.import_sprite,
               "on_mnu_import_workstate_activate":self.import_workstate,
               "on_btn_export_workstate_clicked":self.export_workstate,
               "on_btn_game_ok_clicked":self.game_properties_ok,
               "on_btn_workstate_cancel":self.workstate_cancel,
               "on_btn_new_gamescreen":self.new_game_screen,
               "on_btn_add_obj_to_gamescreen_clicked":self.add_obj_to_gamescreen,
               "show_new_event_popup":self.show_new_event_popup,
               "show_item_popup":self.show_item_popup,
               "new_init_event":(lambda x:self.add_new_event(runtime.EVENT_INIT)),
               "new_iter_event":(lambda x:self.add_new_event(runtime.EVENT_ITERATION)),
               "new_offscreen_event":(lambda x:self.add_new_event(runtime.EVENT_OFFSCREEN)),
               "new_keydown_left_event":(lambda x:self.add_new_event(runtime.EVENT_KEYDOWN * K_LEFT)),
               "new_keydown_right_event":(lambda x:self.add_new_event(runtime.EVENT_KEYDOWN * K_RIGHT)),
               "new_keydown_up_event":(lambda x:self.add_new_event(runtime.EVENT_KEYDOWN * K_UP)),
               "new_keydown_down_event":(lambda x:self.add_new_event(runtime.EVENT_KEYDOWN * K_DOWN)),

               "new_keyup_left_event":(lambda x:self.add_new_event(runtime.EVENT_KEYUP * K_LEFT)),
               "new_keyup_right_event":(lambda x:self.add_new_event(runtime.EVENT_KEYUP * K_RIGHT)),
               "new_keyup_up_event":(lambda x:self.add_new_event(runtime.EVENT_KEYUP * K_UP)),
               "new_keyup_down_event":(lambda x:self.add_new_event(runtime.EVENT_KEYUP * K_DOWN)),
               "new_l_mouse_up_event":(lambda x:self.add_new_event(runtime.EVENT_LMOUSEUP )),
               "new_r_mouse_up_event":(lambda x:self.add_new_event(runtime.EVENT_RMOUSEUP )),
               "new_timer_event":(lambda x:self.add_new_event(runtime.EVENT_TIMER )),
               "on_delete1_activate":self.delete_item,
               "on_popup_new_activate":self.new_item_from_treeview,
               "gamescreen_delete_initial_object":self.gamescreen_delete_initial_object,
               "on_tut_beginner_-_hello_world1_activate": \
                       lambda x:self.show_tutorial("BeginnerTutorial1-HelloWorld.pdf"),
               "on_tut_advanced_-_workstate_parents1_activate": \
                       lambda x:self.show_tutorial("Tutorial-WorkstateParents.pdf"),
               "on_scripting_reference1_activate": \
                       lambda x:self.show_tutorial("python-scripting.pdf"),
               "on_tut_advanced_-_distributing_a_game1_activate": \
                       lambda x:self.show_tutorial("Tutorial-Distributing-Games.pdf")

               }
       # Tell gtk to use these event handlers
       self.wTree.signal_autoconnect(dic)


   def show_about(self,widget=None):
       self.wTree.get_widget("aboutdialog1").show()

   def treeview_click(self,widget=None,event=None):
       if event.button == 3:
           self.show_popup("popup_edit",event)

   def new_item_from_treeview(self,event):
       selection = self.get_widget("treeview1").get_selection()
       model,sel_iter = selection.get_selected()

       obj = model.get_value(sel_iter, 0)
       # TODO: Pop up a "Are you sure" dialogue
       try:
           if obj.objtype == "Gameobject":
               self.new_game_object()
           elif obj.objtype == "Sprite":
               # TODO
               pass
           elif obj.objtype == "Gamescreen":
               self.new_game_screen()
           elif obj.objtype == "Workstate":
               self.new_workstate()

           self.treeviewhelp.update_item_list()
       except Exception, inst:
           objtype=model.get_value(sel_iter,2)
           if objtype == "gamescreens":
               self.new_game_screen()
           elif objtype == "workstates":
               self.new_workstate()
           elif objtype == "gameobjects":
               self.new_game_object()
           pass

   def add_new_event(self,event):

       if not self.selectedworkstate.actions.has_key(event):
           self.selectedworkstate.actions[event] = "\n"
           cb = self.get_widget("cbxworkstateevents")
           model = cb.get_model()
           model.append([event_names.get(event,str(event)),event])
           cb.set_model(model)
           self.change_event_selected()


   def show_new_event_popup(self,widget=None,event=None):
       self.show_popup("popup_events",event)

   def show_item_popup(self,widget=None,event=None):
       self.show_popup("popup_edit",event)

   def show_game_properties(self,widget=None):
       """Show the Game Properties window"""
       self.get_widget("wnd_game").show()
       self.get_widget("txt_game_name").set_text(str(self.game.title))
       self.get_widget("txt_initial_gamescreen").set_text(str(self.game.startscreen))

       text = self.get_widget("textview_load_events")
       textbuffer = text.get_buffer()
       try:
           textbuffer.set_text(self.game.initcode)
       except: pass

       # TODO :
       # Populate the selection box

   def new_game(self,widget=None):
       self.game = game.Game("")
       self.show_game_properties()
       self.treeviewhelp.clear()
       self.treeviewhelp.populate_from_game(self.game)


   def game_properties_ok(self,widget=None):
       self.game.title = self.get_widget("txt_game_name").get_text()
       self.get_widget("wnd_main").set_title(self.game.title + " - Game Baker")
       self.get_widget("wnd_game").hide()
       self.game.startscreen = self.get_widget("txt_initial_gamescreen").get_text()
       if not self.game.gamescreens.has_key(self.game.startscreen):    
           self.game.gamescreens[self.game.startscreen] = self.game.gamescreen((800,600),self.game.startscreen)
       text = self.get_widget("textview_load_events")
       textbuffer = text.get_buffer()
       startiter, enditer = textbuffer.get_bounds()
       self.game.initcode = textbuffer.get_text(startiter,enditer)
       self.treeviewhelp.update_item_list()


   def object_ok(self,widget=None):
       oldname = find_item_name(self.game.gameobjects,self.selectedobject)
       newname = self.get_widget("txt_obj_name").get_text()
       if not oldname == newname and not self.game.gameobjects.has_key(newname):
       #TODO: needs to print error message saying that the name already exists.
           self.game.gameobjects[newname] = self.selectedobject
           del self.game.gameobjects[oldname]
           self.selectedobject.name = newname
       self.treeviewhelp.update_item_list()

       if not self.get_widget("txt_obj_sprite").get_text()=="":
           self.selectedobject.sprite = self.get_widget("txt_obj_sprite").get_text()
       else:
           self.selectedobject.sprite = None

       # Change Workstate
       cb = self.get_widget("cbx_workstateoptns")
       try:
           self.selectedobject.baseworkstate= str(cb.get_model()[cb.get_active()][0])
       except: pass


       # set x,y values
       self.selectedobject.x = self.get_widget("spin_object_x").get_value_as_int()
       self.selectedobject.y = self.get_widget("spin_object_y").get_value_as_int()

       self.get_widget("wnd_Object").hide()

   def gamescreen_ok(self,widget=None):
       oldname = find_item_name(self.game.gamescreens,self.selectedgamescreen)
       newname = self.get_widget("txt_gamescreen_name").get_text()
       if not oldname == newname:
           self.game.gamescreens[newname] = self.selectedgamescreen
           del self.game.gamescreens[oldname]
           self.treeviewhelp.update_item_list()
   
       r = int( self.get_widget("txt_gamescreen_bg_r").get_text() )
       g = int( self.get_widget("txt_gamescreen_bg_g").get_text() )
       b = int( self.get_widget("txt_gamescreen_bg_b").get_text() )
       self.selectedgamescreen.color  = (r,g,b)
       # Itterate through list and update startobjects
       treeview =  self.get_widget("treeview_gamescreen_objects")
       model = treeview.get_model()

       # Need TODO - change this so it stores a string, not a reference (in engine too)
       startobjects = [m[0] for m in model]
       self.selectedgamescreen.startobjects = startobjects


       self.get_widget("wnd_gamescreen").hide()

   def gamescreen_delete_initial_object(self,widget=None):
       treeview =  self.get_widget("treeview_gamescreen_objects")
       #model = treeview.get_model()
       selection = treeview.get_selection()
       model,sel_iter = selection.get_selected()

       if not sel_iter is None:
           del model[sel_iter]


   def workstate_ok(self,widget=None):
       oldname = find_item_name(self.game.workstates,self.selectedworkstate)
       newname = self.get_widget("txt_workstate_name").get_text()
       if not oldname == newname and not self.game.workstates.has_key(newname):
           #TODO: print error message.
           self.game.workstates[newname] = self.selectedworkstate
           del self.game.workstates[oldname]

           self.treeviewhelp.update_item_list()

       inherits = self.get_widget("txt_workstate_inherits").get_text()
       if inherits == "":
           self.selectedworkstate.inherits = None
       else:
           self.selectedworkstate.inherits = inherits

       self.get_widget("wnd_workstate").hide()

   

   def sprite_ok(self,widget=None):
       oldname = find_item_name(self.game.sprites,self.selectedsprite)
       newname = self.get_widget("txt_sprite_name").get_text()
       if not oldname == newname:
           self.game.sprites[newname] = self.selectedsprite
           del self.game.sprites[oldname]

           self.treeviewhelp.update_item_list()

       self.selectedsprite.framerate = self.get_widget("spin_sprite_framerate").get_value_as_int()

       self.get_widget("wnd_sprite").hide()
       


   def workstate_cancel(self,widget=None):
       self.get_widget("wnd_workstate").hide()


   def change_event_selected(self,widget=None):


       # Get the currently selected event code
       text = self.get_widget("text_event_script")
       textbuffer = text.get_buffer()
       # Warn if the existing event is not saved.
       # Have to try this as it's not set initially
       startiter, enditer = textbuffer.get_bounds()
       if widget is not None:
           if self.selectedworkstate.actions[self.selected_workstate_event] \
                                                 != textbuffer.get_text(startiter, enditer):
                msg = GUI.msgbox.gbYesNoMsgbox("<p>There are unsaved changes.</p><p>Do you wish to save changes to this event?</p>", modal=True)
                check = msg.run()
                msg.destroy()
                if check == gtk.RESPONSE_YES:
                    self.selected_workstate.actions[self.selected_workstate_event] = textbuffer.get_text(startiter, enditer)


       cb = self.get_widget("cbxworkstateevents")
       active = cb.get_active()
       model = cb.get_model()

       textbuffer.set_text(self.selectedworkstate.actions.get(int(model[active][1]),""))
       self.selected_workstate_event = int(model[active][1])

   def save_event(self,widget=None):
       cb = self.get_widget("cbxworkstateevents")
       active = cb.get_active()
       model = cb.get_model()

       text = self.get_widget("text_event_script")
       textbuffer = text.get_buffer()
       startiter, enditer = textbuffer.get_bounds()
       script = textbuffer.get_text(startiter,enditer)
       self.selectedworkstate.actions[int(model[active][1])] = script

   def choose_background_colour_gamescreen(self,widget=None):
       # Show Colour Selection
       colorseldlg = gtk.ColorSelectionDialog("Background Colour")

       # Get the ColorSelection widget
       colorsel = colorseldlg.colorsel
       colorsel.set_has_opacity_control(False)

       try:
           colour = self.selectedgamescreen.color
       except:
           colour = (255,255,255)

       gdkcolour = gtk.gdk.Color()

       gdkcolour.red = colour[0] *65535 / 255
       gdkcolour.green = colour[1]*65535 / 255
       gdkcolour.blue = colour[2]*65535 / 255
       colorsel.set_current_color(gdkcolour)

       self.gdkcolour = gdkcolour
       def change_colour(widget = None):
           self.gdkcolour = colorsel.get_current_color()

       colorsel.connect("color_changed", change_colour)

       response = colorseldlg.run()
       gdkcolour = self.gdkcolour

       if response -- gtk.RESPONSE_OK:
           self.get_widget("txt_gamescreen_bg_r").set_text(str(gdkcolour.red * 255 / 65535))
           self.get_widget("txt_gamescreen_bg_g").set_text(str(gdkcolour.green* 255 / 65535))
           self.get_widget("txt_gamescreen_bg_b").set_text(str(gdkcolour.blue* 255 / 65535))
       else:
           pass

       colorseldlg.hide()



   def delete_item(self,widget=None,prop2 = None, prop3 = None):
       selection = self.get_widget("treeview1").get_selection()
       model,sel_iter = selection.get_selected()

       obj = model.get_value(sel_iter, 0)
       # To Do: Pop up a "Are you sure" dialogue
       try:
           if obj.objtype == "Gameobject":
               self.delete_gameobject(obj)
           elif obj.objtype == "Sprite":
               self.delete_sprite(obj)
           elif obj.objtype == "Gamescreen":
               self.delete_gamescreen(obj)
           elif obj.objtype == "Workstate":
               self.delete_workstate(obj)

           self.treeviewhelp.update_item_list()
       except Exception, inst:
           pass


   def add_child_workstate(self,widget=None):
       selection = self.get_widget("treeview1").get_selection()
       model,sel_iter = selection.get_selected()
       obj = model.get_value(sel_iter, 0)

       try:
           if obj.objtype == "Workstate":
               ws = self.new_workstate()
               ws.inherits = find_item_name(self.game.workstates,obj)
       except Exception, inst:
           print inst



   def open_properties(self,widget=None,prop2 = None, prop3 = None):
       selection = self.get_widget("treeview1").get_selection()
       model,sel_iter = selection.get_selected()

       obj = model.get_value(sel_iter, 0)
       try:
           if obj.objtype == "Gameobject":
               self.get_widget("wnd_Object").show()
               # Set Name
               self.get_widget("txt_obj_name").set_text(find_item_name(self.game.gameobjects,obj))

               if not obj.sprite is None:
                   self.get_widget("txt_obj_sprite").set_text(obj.sprite)
               else:
                   self.get_widget("txt_obj_sprite").set_text("")

               model = gtk.ListStore(str)
               for ws in self.game.workstates.keys():
                   model.append([ws])
               cb = self.get_widget("cbx_workstateoptns")
               cb.set_model(model)
               try:
                   cb.set_active(self.game.workstates.keys().index(obj.baseworkstate))
               except: #pass
                   cb.set_active(-1)


               try:
                   self.get_widget("spin_object_x").set_value(int(obj.x))
               except: self.get_widget("spin_object_x").set_value(0)

               try:
                   self.get_widget("spin_object_y").set_value(int(obj.y))
               except: self.get_widget("spin_object_y").set_value(0)

               self.selectedobject = obj


           elif obj.objtype == "Sprite":
               self.get_widget("txt_sprite_name").set_text(find_item_name(self.game.sprites,obj))
               self.get_widget("lbl_sprite_frames").set_text(str( obj.number_of_frames() ))
               self.get_widget("spin_sprite_framerate").set_value(int(obj.framerate))

               self.selectedsprite = obj

               self.get_widget("wnd_sprite").show()

           elif obj.objtype == "Gamescreen":
               self.get_widget("wnd_gamescreen").show()
               self.get_widget("txt_gamescreen_name").set_text(find_item_name(self.game.gamescreens,obj))
               try:
                   color = obj.color
               except:
                   color=(255,255,255)

               self.get_widget("txt_gamescreen_bg_r").set_text( str(color[0]) )
               self.get_widget("txt_gamescreen_bg_g").set_text( str(color[1]) )
               self.get_widget("txt_gamescreen_bg_b").set_text( str(color[2]) )

               # Show List of options for objects
               model = gtk.ListStore(str)
               for go in self.game.gameobjects.keys():
                   model.append([go])
               cb = self.get_widget("cbx_gamescreen_object_options")
               cb.set_model(model)

               self.selectedgamescreen = obj


               treeview =  self.get_widget("treeview_gamescreen_objects")
               treestore = gtk.TreeStore(gobject.TYPE_PYOBJECT, gobject.TYPE_STRING,gobject.TYPE_STRING)

               for go in obj.startobjects:
                   insert_iter = treestore.append(None, [go,go.name,go.name])
               treeview.set_model(treestore)


           elif obj.objtype == "Workstate":
               self.get_widget("wnd_workstate").show()
               self.get_widget("txt_workstate_name").set_text(find_item_name(self.game.workstates,obj))

               if obj.inherits is not None:
                   self.get_widget("txt_workstate_inherits").set_text(obj.inherits)
               else:
                   self.get_widget("txt_workstate_inherits").set_text("")

               cb = self.get_widget("cbxworkstateevents")

               model = gtk.ListStore(str,int)
               model.clear()
               for event in obj.actions.keys():
                   model.append([event_names.get(event,str(event)),event])

               cb.set_model(model)

               cb.set_active(0)
               self.selectedworkstate = obj
               self.change_event_selected()
               

       except Exception, inst:
           print inst

   def add_obj_to_gamescreen(self,widget=None):
       # Get current selection
       cb =  self.get_widget("cbx_gamescreen_object_options")
       active = cb.get_active()
       model = cb.get_model()
       obj_name = model[active][0]

       # Now add this to the list        
       treeview =  self.get_widget("treeview_gamescreen_objects")
       model = treeview.get_model()
       obj = self.game.gameobjects[obj_name]
       model.append(None,[obj,obj_name,obj_name])

   def add_item_choice(self,widget=None):
       self.get_widget("wnd_new_item").show()

   def import_sprite(self,widget=None):

       file_open = GUI.file_dialog(title="Import Sprite File",style="open")

       file_open.add_sprite_filter()
       file_open.add_all_files_filter()
       filename = ""

       if file_open.run() == gtk.RESPONSE_OK:
           filename = file_open.get_filename()
       file_open.destroy()

       self.import_external_sprite(filename)

       self.treeviewhelp.update_item_list()
       

   def open_file(self,widget = None):
       
       file_open = GUI.file_dialog(title="Open Game File",style="open")

       file_open.add_game_filter()
       file_open.add_all_files_filter()
       filename = ""

       if file_open.run() == gtk.RESPONSE_OK:
           filename = file_open.get_filename()
       file_open.destroy()
       
       if not filename == "":
           import gbfileio
           self.game = gbfileio.loadgame(filename)
           self.treeviewhelp.clear()
           self.treeviewhelp.populate_from_game(self.game)
           self.filename = filename
           os.chdir(os.path.split(filename)[0])
           self.get_widget("wnd_main").set_title(self.game.title + " - Game Baker")

   def closegame(self,widget=None):
       """Close the currently open game"""
       self.treeviewhelp.clear()
       self.game=None
       self.get_widget("wnd_main").set_title("- Game Baker")

   def save_file(self,widget = None):
       if self.filename == "":
           self.save_file_as(widget)
       else:
           import gbfileio
           gbfileio.savegame(self.filename,self.game)

   def save_file_as(self,widget = None):

       file_save = GUI.file_dialog(title="Save Game File",style="save")
       file_save.add_game_filter()
       file_save.add_all_files_filter()
       filename = ""

       if file_save.run() == gtk.RESPONSE_OK:
           filename = file_save.get_filename()
           if not filename[-3:] == ".gb":
               filename = filename + ".gb"
       file_save.destroy()

       if not filename == "":
           import gbfileio
           gbfileio.savegame(filename,self.game)
           os.chdir(os.path.split(filename)[0])
           self.filename = filename

   def new_game_object(self,widget = None):
       self.add_game_object()
       self.get_widget("wnd_new_item").hide()
       self.treeviewhelp.update_item_list()
       
   def new_workstate(self,widget = None):
       ws = self.add_workstate()
       self.get_widget("wnd_new_item").hide()
       self.treeviewhelp.update_item_list()
       return ws

   def new_game_screen(self,widget=None):
       self.add_gamescreen( resolution=(800,600) )
       self.get_widget("wnd_new_item").hide()    
       self.treeviewhelp.update_item_list()    

   def show_tutorial(self,filename):
       import webbrowser
       webbrowser.open(os.path.join(self.gamebaker_location,"tutorials",filename) )

       
   def import_workstate(self, workstate):
       file_open = GUI.file_dialog(title="Import Workstate",style="open")
       
       file_open.add_workstate_filter()
       file_open.add_all_files_filter()
       filename = ""

       if file_open.run() == gtk.RESPONSE_OK:
           filename = file_open.get_filename()
       file_open.destroy()
        
       if not filename == "":
           import gbfileio
           workstate = gbfileio.loadgame(filename, typ="workstate")
           
           name = workstate.name
           del workstate.name
           if self.game.workstates.has_key(name):
               count = 2
               while self.game.workstates.has_key(name + "%d"%count):
                   count+=1
               name = name + "%d"%count  

           self.game.workstates[name] = workstate

       self.treeviewhelp.update_item_list()   
       

   def export_workstate(self, widget = None):
       workstate = self.selectedworkstate
       workstate.name = find_item_name(self.game.workstates,self.selectedworkstate)
       workstate_save = GUI.file_dialog(title="Export Workstate",style="save")
       workstate_save.add_workstate_filter()
       workstate_save.add_all_files_filter()
       filename = ""

       if workstate_save.run() == gtk.RESPONSE_OK:
           filename = workstate_save.get_filename()
           if not filename[-4:] == ".gbw":
               filename = filename + ".gbw"
       workstate_save.destroy()

       if not filename == "":
           import gbfileio
           gbfileio.savegame(filename, workstate, typ="workstate")

